package ua.lviv.franko.solvers;

import ua.lviv.franko.matrix.RowType;
import ua.lviv.franko.matrix.hash.lu.HashMatrixLUStyle;
import ua.lviv.franko.matrix.hash.lu.LUFactorization;

public class Temp {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// double[][] matrix = new double[][] { { 1.7725815386349424, 0.8862907693174711, 0.451965920603915, 0.23480349624713687 },
		// { 0.8862907693174711, 0.451965920603915, 0.23480349624713687, 0.12414915020348981 },
		// { 0.451965920603915, 0.23480349624713687, 0.12414915020348981, 0.06674884331640826 },
		// { 0.23480349624713687, 0.12414915020348981, 0.06674884331640826, 0.03646391176986939 } };
		// double[] b = new double[] { 1.0, 0.5, 0.25, 0.125 };
		// double[] bGauss = new double[] { 1.0, 0.5, 0.25, 0.125 };
		double[][] matrix = new double[][] { { 2.953682801272087, 1.4768414006360435, 0.7793419219455839, 0.43059218260035403, 0.24767368134949838, 0.14767079914582984 },
				{ 1.4768414006360435, 0.7793419219455839, 0.43059218260035403, 0.24767368134949838, 0.14767079914582984, 0.09095357507463822 },
				{ 0.7793419219455839, 0.43059218260035403, 0.2476736813494984, 0.14767079914582984, 0.09095357507463822, 0.05770702867856858 },
				{ 0.43059218260035403, 0.2476736813494984, 0.14767079914582984, 0.09095357507463823, 0.05770702867856858, 0.03762565949591535 },
				{ 0.24767368134949838, 0.14767079914582984, 0.09095357507463822, 0.05770702867856858, 0.03762565949591535, 0.02515870706279777 },
				{ 0.14767079914582984, 0.09095357507463822, 0.05770702867856858, 0.03762565949591535, 0.02515870706279777, 0.017220624185196976 } };
		double[] b = new double[] { 1.0, 0.5, 0.25, 0.125, 0.0625, 0.03125 };
		// double[] bGauss = new double[] { 1.0, 0.5, 0.25, 0.125, 0.0625, 0.03125 };
		double[][] bGauss = new double[][] { { 1.0, 1.0 }, { 0.5, 0.5 }, { 0.25, 0.25 }, { 0.125, 0.125 }, { 0.0625, 0.0625 }, { 0.03125, 0.03125 } };
		HashMatrixLUStyle hashMatrix = new HashMatrixLUStyle(RowType.ARRAY_TYPE, matrix.length);
		for (int i = 0; i < b.length; i++) {
			for (int j = 0; j < b.length; j++) {
				hashMatrix.setValue(i, j, matrix[i][j]);
			}
		}

		long start = System.nanoTime();
		HashMatrixLUStyle.printMatrix(gauss(matrix, bGauss));
		System.out.println();
		System.out.println("time = " + (System.nanoTime() - start));

		start = System.nanoTime();
		LUFactorization factorization = new LUFactorization(hashMatrix);
		HashMatrixLUStyle.printMatrix(factorization.calculate(b));
		System.out.println();
		System.out.println("time = " + (System.nanoTime() - start));

	}

	public static double[] gauss(double[][] a, double[] b) {
		int n = a.length;
		for (int i = 0; i < n; i++) {
			int best = i;
			for (int j = i + 1; j < n; j++) {
				if (Math.abs(a[j][i]) > Math.abs(a[best][i])) {
					best = j;
				}
			}
			double[] tmp = a[i];
			a[i] = a[best];
			a[best] = tmp;
			double t = b[i];
			b[i] = b[best];
			b[best] = t;

			for (int j = i + 1; j < n; j++) {
				a[i][j] /= a[i][i];
			}
			b[i] /= a[i][i];

			for (int j = 0; j < n; j++) {
				if (j != i && a[j][i] != 0) {
					for (int p = i + 1; p < n; p++) {
						a[j][p] -= a[i][p] * a[j][i];
					}
					b[j] -= b[i] * a[j][i];
				}
			}
		}
		return b;
	}

	public static double[][] gauss(double[][] a, double[][] b) {
		int n = a.length;
		for (int i = 0; i < n; i++) {
			int best = i;
			for (int j = i + 1; j < n; j++) {
				if (Math.abs(a[j][i]) > Math.abs(a[best][i])) {
					best = j;
				}
			}
			double[] tmp = a[i];
			a[i] = a[best];
			a[best] = tmp;
			 
			tmp = b[i];
			b[i] = b[best];
			b[best] = tmp;

			for (int j = i + 1; j < n; j++) {
				a[i][j] /= a[i][i];
			}
			for (int j = 0; j < b[i].length; j++) {
				b[i][j] /= a[i][i];
			}

			for (int j = 0; j < n; j++) {
				if (j != i && a[j][i] != 0) {
					for (int p = i + 1; p < n; p++) {
						a[j][p] -= a[i][p] * a[j][i];
					}
					for (int k = 0; k < b[j].length; k++) {
						b[j][k] -= b[i][k] * a[j][i];
					}

				}
			}
		}
		return b;
	}

}
